Skip to content

Change pretyping of argument closure #2018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Feb 21, 2017

Follow scalac in taking the lub of all formal parameters
instead of requiring that they are all the same.

This conforms to the spec change in

https://github.com/scala/scala/pull/5307/files#diff-5d74b019862ed901d7800b4ace79fb5b

Review by @adriaanm ?

Note this PR is based on #2015. Only the last commit is relevant here.

case-closures (which are represented as Match nodes) have a known
arity just like other function literals. So shape analysis for
overloading resolution should apply to them as well.
Follow scalac in taking the lub of all formal parameters
instead of requiring that they are all the same.

This conforms to the spec change in

  https://github.com/scala/scala/pull/5307/files#diff-5d74b019862ed901d7800b4ace79fb5b
Copy link
Contributor

@adriaanm adriaanm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that we're aligning our spec & impl here, though I also agree that it probably doesn't matter in practice whether we lub argument types or require them to be the same. Personally, I think the lub approach is a bit more aesthetically pleasing :-)

@odersky
Copy link
Contributor Author

odersky commented Feb 22, 2017

@adriaanm Through test failures here I discovered two problems with the LUB approach. The first is the failing test `tests/pos/overloaded.scala'. Here we find:

def combine(f: (Char, Int) => Int): Int = ???
def combine(f: (String, Int) => String): String = ???
val r5 = combine((x: Char, y) => x + y)
val t5: Int = r5
val r6 = combine((x: String, y) => x ++ y.toString)
val t6: String = r6

This used to compile OK, but now gives errors, and scalac produces errors as well:

/Users/odersky/workspace/dotty/tests/pos/overloaded.scala:46: error: type mismatch;
 found   : (Char, Int) => Int
 required: (Any, Int) => ?
  val r5 = combine((x: Char, y) => x + y)
                                ^
/Users/odersky/workspace/dotty/tests/pos/overloaded.scala:48: error: type mismatch;
 found   : (String, Int) => String
 required: (Any, Int) => ?
  val r6 = combine((x: String, y) => x ++ y.toString)
                                  ^

It seems we need a finer resolution which only LUBS those arguments that do not already have a type declared.

The second problem is dotty only, in test file tests/neg/overloaded.scala. Here we have:

def mapX(f: Char => Char): String = ???
def mapX[U](f: U => U): U = ???
mapX(x => x) // error: missing parameter type

We used to get a missing parameter type, but with the LUB change this now compiles into non-sensical code:

Test.mapX[Char^](
  {
    def $anonfun(x: U | Char): U | Char = x
    closure($anonfun)
  }
)

There's an unbound U in the closure. It seems we must get rid of type parameters somehow in the lub. The "same parameter types" approach does not suffer this problem because local type parameters in parameter types would always render them different to other parameter types.

@odersky
Copy link
Contributor Author

odersky commented Feb 22, 2017

The last commit implements the selective LUB change. But the leaking local parameter problem still persists.

@odersky
Copy link
Contributor Author

odersky commented Feb 27, 2017

I am going to close this, because the second problem mentioned above looks too messy to solve, given the limited usefulness.

There's an unbound U in the closure. It seems we must get rid of type parameters somehow in the lub. The "same parameter types" approach does not suffer this problem because local type parameters in parameter types would always render them different to other parameter types.

@odersky odersky closed this Feb 27, 2017
@adriaanm
Copy link
Contributor

It seems we must get rid of type parameters somehow in the lub.

Yes, we approximate abstract types with (unbounded) wildcards. I'll keep an eye on the dotty approach and the collections rework to make sure we stay compatible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants